package com.jwater.core.manager.proxy;

import com.jwater.core.manager.common.ManagerException;
import com.jwater.core.manager.common.MsgKeys;
import com.jwater.core.manager.common.conf.CoreConfParse;
import com.jwater.core.manager.common.model.ProxyInfo;
import com.jwater.core.manager.master.MasterNode;
import com.jwater.core.manager.master.event.ProxyReportInfoEvent;
import com.jwater.core.net.Node;
import com.jwater.core.net.NodeHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @description:代理client管理类
 * @author: jnner
 * @createDate: 2021/2/5
 * @version: 1.0
 */
public class ProxyManager {
    protected static Logger logger = LoggerFactory.getLogger(ProxyManager.class);

    private List<ProxyInfo> proxyInfos;
    private Map<String, ProxyClient> clients = new HashMap<>();
    private int masterId = -1;

    public ProxyManager(List<ProxyInfo> proxyInfos) {
        this.proxyInfos = proxyInfos;
    }

    public void setMasterId(int masterId) {
        this.masterId = masterId;
    }

    /**
     * 启动
     *
     * @param coreConfParse
     */
    public void start(CoreConfParse coreConfParse) {
        for (ProxyInfo proxyInfo : proxyInfos) {
            ProxyClient client = new ProxyClient();
            client.setMasterId(masterId);
            client.start(proxyInfo.getHost(), proxyInfo.getPort(), coreConfParse.getNodeInfo(proxyInfo.getHost()));
            clients.put(proxyInfo.getHost(), client);
        }
        waitConnect();
    }

    /**
     * 重启
     *
     * @param coreConfParse
     * @param changeProxyInfos
     */
    public void reboot(CoreConfParse coreConfParse, Map<String, ProxyInfo> changeProxyInfos) {
        for (Map.Entry<String, ProxyInfo> en : changeProxyInfos.entrySet()) {
            ProxyClient oldProxyClient = this.clients.get(en.getKey());
            if (oldProxyClient != null) {
                oldProxyClient.stop();
                clients.remove(en.getKey());
            }
            ProxyInfo proxyInfo = en.getValue();
            ProxyClient client = new ProxyClient();
            client.setMasterId(masterId);
            client.start(proxyInfo.getHost(), proxyInfo.getPort(), coreConfParse.getNodeInfo(proxyInfo.getHost()));
            clients.put(proxyInfo.getHost(), client);
        }
        waitConnect();
    }

    /**
     * 等待连接
     */
    private void waitConnect() {
        boolean isRun = true;
        while (isRun) {
            isRun = false;
            for (ProxyClient client : clients.values()) {
                if (client.getConnectCount() <= 0) {
                    isRun = true;
                }
            }
        }
    }

    /**
     * 关闭所有的client
     */
    public void close() {
        for (ProxyClient client : clients.values()) {
            client.stop();
        }
    }

    /**
     * 根据主机获取代理client
     *
     * @param host
     * @return
     */
    public ProxyClient getProxyClient(String host) {
        return clients.get(host);
    }

    /**
     * 随机选择代理客户端
     *
     * @return
     */
    public ProxyClient chooseProxyClient() {
        List<ProxyClient> onlineClients = getOnlineClients();
        if (onlineClients.isEmpty()) {
            throw new ManagerException("can not choose proxy,all offline");
        }
        return onlineClients.get(new Random(System.currentTimeMillis()).nextInt(onlineClients.size()));
    }

    /**
     * 获取所有在线的代理客户端
     *
     * @return
     */
    public List<ProxyClient> getOnlineClients() {
        List<ProxyClient> onlineClients = new ArrayList<ProxyClient>();
        for (ProxyClient client : clients.values()) {
            if (client.isConnect()) {
                onlineClients.add(client);
            }
        }
        return onlineClients;
    }
}
